﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using Excel = Microsoft.Office.Interop.Excel;
using System.Windows.Forms;
using System.Drawing;

namespace ElWireControl
{
    public class Datahandling
    {
        public class ExcelData : INotifyPropertyChanged
        {
            private string _name;
            private uint _address;
            private int _contentIndexPointer;
            private int _sequenceEnd;
            private string _comment = "hallo";
            private int _battery;
            //private Signalstärke _signal_rssi;
            //private Signalstärke _signal_lqi;
            private int _signal_rssi; 
            private int _signal_lqi;

            public event PropertyChangedEventHandler PropertyChanged;

            public string name
            {
                get
                {
                    return _name;
                }
                set
                {
                    _name = value;
                    this.NotifyPropertyChanged("name");
                }
            }
            public uint address
            {
                get
                {
                    return _address;
                }
                set
                {
                    _address = value;
                    this.NotifyPropertyChanged("address");
                }
            }
            public int contentIndexPointer
            {
                get
                {
                    return _contentIndexPointer;
                }
                set
                {
                    _contentIndexPointer = value;
                    if (value < content.Count)
                    {
                        _comment = content[value <= 0 ? 0 : value - 1].comment;
                    }
                    else
                    {
                        _comment = "";
                    }
                    comment = _comment;
                    this.NotifyPropertyChanged("contentIndexPointer");
                }
            }
            public int sequenceEnd
            {
                get
                {
                    return _sequenceEnd;
                }
                set
                {
                    _sequenceEnd = value;
                    this.NotifyPropertyChanged("sequenceEnd");
                }
            }
            public string comment
            {
                get
                {
                    return _comment;
                }
                set
                {
                    _comment = value;
                    this.NotifyPropertyChanged("comment");
                }
            }
            public int battery          // Akkuzustand in Prozent
            {
                get
                {
                    return _battery;
                }
                set
                {
                    _battery = value;
                    this.NotifyPropertyChanged("battery");
                }
            }

            public int signal_rssi  // Funksignal-Signalstärke [je höher, desto besser]
            {
                get
                {
                    return _signal_rssi;
                }
                set
                {
                    _signal_rssi = value;
                    this.NotifyPropertyChanged("signal_rssi");
                }
            }
            public int signal_lqi  // Funksignal-Signalstärke [je höher, desto besser]
            {
                get
                {
                    return _signal_lqi;
                }
                set
                {
                    _signal_lqi = value;
                    this.NotifyPropertyChanged("signal_lqi");
                }
            }

            //public Signalstärke signal_rssi  // Funksignal-Signalstärke [je höher, desto besser]
            //{
            //    get
            //    {
            //        return _signal_rssi;
            //    }
            //    set
            //    {
            //        _signal_rssi = value;
            //        this.NotifyPropertyChanged("signal_rssi");
            //    }
            //}
            //public Signalstärke signal_lqi  // Funksignal-Signalstärke [je höher, desto besser]
            //{
            //    get
            //    {
            //        return _signal_lqi;
            //    }
            //    set
            //    {
            //        _signal_lqi = value;
            //        this.NotifyPropertyChanged("signal_lqi");
            //    }
            //}


            public List<ElWireData> content = new List<ElWireData>();

            private void NotifyPropertyChanged(string name)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        public enum Signalstärke
        {
            unbekannt,
            //schlecht,
            //ausreichend,
            //gut,
            //hervorragend
        }


        public class ElWireData
        {
            public uint address;                // Sendeadresse
            public int cmdSendtime_ms = 0;      // Zeit in Millisekunden, bei der das Kommando gesendet wird
            public string cmd;                  // Kommando
            public string comment;              // Kommentar/Bemerkungen
        }

        public static List<ElWireData> ReadData(string filename)
        {
            List<ElWireData> liste = new List<ElWireData>();

            // schritt 1: lese excel
            List<ExcelData> exceldata = ReadExcel(filename);

            // schritt 2: füge listen zusammen
            foreach (var item in exceldata)
            {
                foreach (var content in item.content)
                    liste.Add(content);
            }

            // schritt 3: sortiere die liste nach cmdSendtime_ms
            liste.Sort(delegate(ElWireData a, ElWireData b)
            {
                // sortiert die Daten nach cmdSendtime_ms in aufsteigender Reihenfolge
                return a.cmdSendtime_ms.CompareTo(b.cmdSendtime_ms);
                //// sortiert die Daten nach cmdSendtime_ms in absteigender Reihenfolge
                //return b.cmdSendtime_ms.CompareTo(a.cmdSendtime_ms);
            });

            return liste;
        }

        public static List<ExcelData> ReadExcel(string filename)
        {
            ExcelData data;
            ElWireData eldata;
            Excel.Range range;
            List<ExcelData> deviceData = new List<ExcelData>();

            //define Excel
            Excel.Application XlsApp = new Excel.Application();
            Excel.Workbook Workbook;
            Excel.Worksheet WorkSheet;
            object missing = System.Reflection.Missing.Value;

            //Get a new workbook.
            Workbook = (Excel.Workbook)(XlsApp.Workbooks.Open(filename, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing));
            try
            {
                for (int i = 1; i <= Workbook.Sheets.Count; i++)
                {
                    data = new ExcelData();
                    WorkSheet = (Excel.Worksheet)Workbook.Worksheets.get_Item(i);
                    //Excel wird sichtbar / false = unsichtbar
                    XlsApp.Visible = false;

                    // lese Header
                    data.name = Convert.ToString(WorkSheet.get_Range("B1", missing).Text);
                    data.address = StringToUInt(WorkSheet.get_Range("B2", missing).Text);
                    data.contentIndexPointer = 0;
                    data.sequenceEnd = 0;

                    // Adresse bereits vorhanden?
                    foreach (var item in deviceData)
                    {
                        if (item.address == data.address)
                        {
                            System.Windows.Forms.MessageBox.Show(string.Format("Datenfile einlesen abgebrochen. Die Geräte-Nr '{0}' ist mehrfach vorhanden.", data.address));
                            throw new Exception();
                        }
                    }

                    // lese Daten
                    range = WorkSheet.UsedRange;
                    int zeile = 5;  // Ab dieser Zeile beginnen die Daten
                    string starttime;
                    do
                    {
                        eldata = new ElWireData();


                        // generiert Kommando aus Adresse und Payload-Daten
                        eldata.cmd = string.Format("FC{0:00}SE{1}\r\n",
                                                    data.address,
                                                    ConvertExceldataToCmd((System.Array)WorkSheet.get_Range(string.Format("C{0}", zeile.ToString()),
                                                                                                            string.Format("L{0}", zeile.ToString())).Cells.Value));

                        eldata.comment = string.Format("{0}", WorkSheet.get_Range(string.Format("M{0}", zeile.ToString()), missing).Text);
                        eldata.address = data.address;

                        // liest Zeit aus, wann das Kommando gesendet werden muss
                        starttime = string.Format("{0}", WorkSheet.get_Range(string.Format("A{0}", zeile.ToString()), missing).Text);
                        if (starttime.Length <= 0)
                            continue;   // Abbruch
                        eldata.cmdSendtime_ms = (int)(Convert.ToDouble(starttime)*1000);

                        data.sequenceEnd = eldata.cmdSendtime_ms;
                        data.content.Add(eldata);
                        zeile++;
                    } while (starttime.Length > 0);

                    if (data.content.Count > 0)
                        deviceData.Add(data);
                }

                XlsApp.Workbooks.Close();
                XlsApp.Quit();
            }
            catch (Exception)
            {
                XlsApp.Workbooks.Close();
                XlsApp.Quit();
            }
            return new List<ExcelData>(deviceData);
        }

        private static string ConvertExceldataToCmd(Array array)
        {
            string tmp = "";
            for (int i = 1; i <= array.Length; i++)
            {
                if (array.GetValue(1, i) == null)
                    tmp += "0";
                else
                    tmp += array.GetValue(1, i).ToString();
            }

            return string.Format("{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}",
                                    tmp[1], // body
                                    tmp[7],// leg right
                                    tmp[4],// hand left
                                    tmp[6],// leg left
                                    tmp[3],// arm right
                                    tmp[8],// foot left
                                    tmp[0],// head
                                    tmp[9],// foot right
                                    tmp[2],// arm left
                                    tmp[5]// hand right
                                    );
        }

        private static uint StringToUInt(dynamic stringvalue)
        {
            try
            {
                return Convert.ToUInt32(stringvalue);
            }
            catch (Exception)
            {
                return 0;
            }
        }

        private static int DoubleStringToInt(dynamic stringvalue)
        {
            try
            {
                return (int)(Convert.ToDouble(stringvalue) * 1000);
            }
            catch (Exception)
            {
                return 0;
            }
        }
    }


    namespace Sample
    {
        public class DataGridViewProgressColumn : DataGridViewImageColumn
        {
            public DataGridViewProgressColumn()
            {
                CellTemplate = new DataGridViewProgressCell();
            }
        }
    }
    namespace Sample
    {
        class DataGridViewProgressCell : DataGridViewImageCell
        {
            // Used to make custom cell consistent with a DataGridViewImageCell
            static Image emptyImage;
            static DataGridViewProgressCell()
            {
                emptyImage = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            public DataGridViewProgressCell()
            {
                this.ValueType = typeof(int);
            }
            // Method required to make the Progress Cell consistent with the default Image Cell. 
            // The default Image Cell assumes an Image as a value, although the value of the Progress Cell is an int.
            protected override object GetFormattedValue(object value,
                                int rowIndex, ref DataGridViewCellStyle cellStyle,
                                TypeConverter valueTypeConverter,
                                TypeConverter formattedValueTypeConverter,
                                DataGridViewDataErrorContexts context)
            {
                return emptyImage;
            }
            protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
            {
                try
                {
                    float voltage = (float)((int)value) / 1000.0f;
                    float percentage = ((float)Battery.ConvertMillivoltageToPercent((int)value) / 100.0f); // Need to convert to float before division; otherwise C# returns int which is 0 for anything but 100%.
                    Brush backColorBrush = new SolidBrush(cellStyle.BackColor);
                    Brush foreColorBrush = new SolidBrush(cellStyle.ForeColor);
                    // Draws the cell grid
                    base.Paint(g, clipBounds, cellBounds,
                     rowIndex, cellState, value, formattedValue, errorText,
                     cellStyle, advancedBorderStyle, (paintParts & ~DataGridViewPaintParts.ContentForeground));

                    string text = string.Format("{0:0.0} V | {1:0} %", voltage, percentage * 100);
                    if (percentage <= 0.0)
                    {
                        // draw the text
                        g.FillRectangle(new SolidBrush(Color.Red), cellBounds.X + 2, cellBounds.Y + 2, cellBounds.Width - 4, cellBounds.Height - 4);
                        if (this.DataGridView.CurrentRow.Index == rowIndex)
                            g.DrawString(text, cellStyle.Font, new SolidBrush(cellStyle.SelectionForeColor), cellBounds.X + 2, cellBounds.Y + 2);
                        else
                            g.DrawString(text, cellStyle.Font, foreColorBrush, cellBounds.X + 2, cellBounds.Y + 2);
                    }
                    else if (percentage < 0.20)
                    {
                        // Draw the progress bar and the text
                        g.FillRectangle(new SolidBrush(Color.Red), cellBounds.X + 2, cellBounds.Y + 2, Convert.ToInt32((percentage * (cellBounds.Width - 4))), cellBounds.Height - 4);
                        g.DrawString(text, cellStyle.Font, foreColorBrush, cellBounds.X + 2, cellBounds.Y + 2);
                    }
                    else
                    {
                        // Draw the progress bar and the text
                        g.FillRectangle(new SolidBrush(Color.Green), cellBounds.X + 2, cellBounds.Y + 2, Convert.ToInt32((percentage * (cellBounds.Width - 4))), cellBounds.Height - 4);
                        g.DrawString(text, cellStyle.Font, foreColorBrush, cellBounds.X + 2, cellBounds.Y + 2);
                    }
                }
                catch (Exception) { }

            }
        

            //protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
            //{
            //    try
            //    {
            //        int progressVal = (int)value;
            //        float percentage = ((float)progressVal / 100.0f); // Need to convert to float before division; otherwise C# returns int which is 0 for anything but 100%.
            //        Brush backColorBrush = new SolidBrush(cellStyle.BackColor);
            //        Brush foreColorBrush = new SolidBrush(cellStyle.ForeColor);
            //        // Draws the cell grid
            //        base.Paint(g, clipBounds, cellBounds,
            //         rowIndex, cellState, value, formattedValue, errorText,
            //         cellStyle, advancedBorderStyle, (paintParts & ~DataGridViewPaintParts.ContentForeground));
            //        if (percentage > 0.0)
            //        {
            //            // Draw the progress bar and the text
            //            g.FillRectangle(new SolidBrush(Color.FromArgb(203, 235, 108)), cellBounds.X + 2, cellBounds.Y + 2, Convert.ToInt32((percentage * cellBounds.Width - 4)), cellBounds.Height - 4);
            //            g.DrawString(progressVal.ToString() + "%", cellStyle.Font, foreColorBrush, cellBounds.X + (cellBounds.Width / 2) - 5, cellBounds.Y + 2);

            //        }
            //        else
            //        {
            //            // draw the text
            //            if (this.DataGridView.CurrentRow.Index == rowIndex)
            //                g.DrawString(progressVal.ToString() + "%", cellStyle.Font, new SolidBrush(cellStyle.SelectionForeColor), cellBounds.X + 6, cellBounds.Y + 2);
            //            else
            //                g.DrawString(progressVal.ToString() + "%", cellStyle.Font, foreColorBrush, cellBounds.X + 6, cellBounds.Y + 2);
            //        }
            //    }
            //    catch (Exception e) { }

            //}
        }

    }
}
